﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class GrassBatch : MonoBehaviour {
    public float pointSize = 1;
    private Mesh mesh;

    public Texture2D grassTexture;
    public float grassRange = 100;
    public float mapSize = 1024;
    public float imgSize = 2048;
    public float terrainHeightSize = 2049;
    public float heightTerrain = 25;
    public int grassCount = 100;


    private float[,,] allColors;
    private float[,] allHeight;

	// Use this for initialization
	void Start () {
        //allColors = grassTexture.GetPixels();
        Random.InitState(0);
        var td = Terrain.activeTerrain.terrainData;
        var alphaWidth = td.alphamapWidth;
        var alphaHeight = td.alphamapHeight;
        var alphaColors = td.GetAlphamaps(0, 0, alphaWidth, alphaHeight);
        Debug.Log("AlphaMap: "+alphaWidth+":"+alphaHeight);
        allColors = alphaColors;



        var w2 = td.heightmapWidth;
        var h2 = td.heightmapHeight;
        allHeight = Terrain.activeTerrain.terrainData.GetHeights(0, 0, w2, h2);
        Debug.Log("heightMapScale: " + td.heightmapScale);

        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;
        GenPoints();
        GenOneGrass();
	}
    private LoadModel.VetexAttrib[] points;

    private int GetImgPos(float v)
    {
       return Mathf.FloorToInt(Mathf.Min(Mathf.Max(0, Mathf.FloorToInt(v)), imgSize-1));
    }
    private bool TestPoint(Vector3 p)
    {
        var rp = p + transform.position;
        rp = rp / mapSize;
        rp.y = 0;

        var imgPos = imgSize * rp ;
        //var colPos =  GetImgPos(imgPos.z) * imgSize + GetImgPos(imgPos.x);
        var cy = GetImgPos(imgPos.z);
        var cx = GetImgPos(imgPos.x);
        //var c = allColors[(int)(colPos)];
        var cr = allColors[cy, cx, 0];
        var cg = allColors[cy, cx, 1];
        var cb = allColors[cy, cx, 2];
        var ca = allColors[cy, cx, 3];
        //return (c.g > 0.1f) && (c.b < 0.1f) && (c.a > 0.1f); 
        return cg > 0.1f && cb < 0.1f && ca < 0.1f && cr < 0.1f;
    }

    private float GetTerrainHeight(Vector3 p)
    {
        var rp = p + transform.position;
        rp = rp / mapSize;
        rp.y = 0;

        var imgPos = imgSize * rp;
        var ty = GetImgPos(imgPos.z);
        var tx = GetImgPos(imgPos.x);
        var hValue = allHeight[ty, tx] * heightTerrain;
        return hValue+0.7f;
    }

    private void GenPoints()
    {
        var totalNum = grassCount;
        //points = new LoadModel.VetexAttrib[totalNum];
        var pp = new List<LoadModel.VetexAttrib>();
        for(var i = 0; i < totalNum; i++)
        {
            var px = Random.Range(-grassRange, grassRange);
            var pz = Random.Range(-grassRange, grassRange);
            var tp = new Vector3(px, 0, pz);
            var ret = TestPoint(tp);
            if (ret)
            {
                var hv = GetTerrainHeight(tp);
                tp = new Vector3(px, hv, pz);
                Debug.Log("GrassHei:" + tp);
                var p = new LoadModel.VetexAttrib()
                {
                    position = tp,
                    color = new Color(1, 1, 1, 1),
                };
                //points[i] = p;
                pp.Add(p);
            }else
            {
                /*
                Debug.Log("GrassNot:" + tp);

                var hv = GetTerrainHeight(tp);
                tp = new Vector3(px, hv, pz);
                Debug.Log("GrassHei:" + tp);
                var p = new LoadModel.VetexAttrib()
                {
                    position = tp,
                    color = new Color(1, 0, 0, 1),
                };
                //points[i] = p;
                pp.Add(p);
                */
            }
        }
        points = pp.ToArray();
    }

    private void GenOneGrass()
    {
        /*
        var points = new LoadModel.VetexAttrib[]
        {
            new LoadModel.VetexAttrib()
            {
                position = new Vector3(0, 0, 0),
                color = new Color(1, 1, 1, 1),
            },
        };
        */

        var triangles = new Vector3[points.Length * 4];
        var indecies = new int[points.Length * 6];
        var colors = new Color[points.Length * 4];
        var normals = new Vector3[points.Length * 4];
        var uvs = new Vector2[points.Length * 4];

        var cameraPos = Camera.main.transform.position;
        var cameraNormal = -Camera.main.transform.forward;
        for(var i = 0; i < points.Length; i++)
        {
            var point = points[i];
            var p = point.position;

            //var dir = cameraPos - p;
            //dir.Normalize();
            var dir = cameraNormal;
            var leftX = Vector3.Cross(Vector3.up, dir);
            var upDirY = Vector3.Cross(dir, leftX);
            var deg = Random.Range(-15, 15);
            //var deg = 30;
            var rot = Quaternion.Euler(0, deg, 0);

            Matrix4x4 mat = new Matrix4x4();
            mat.SetRow(0, leftX);
            mat.SetRow(1, upDirY);
            mat.SetRow(2, dir);
            mat.SetRow(3, new Vector4(0, 0, 0, 1));

            //var newNormal = mat* (rot * Vector3.forward);
            var rotMat = Matrix4x4.TRS(Vector3.zero, rot, Vector3.one);
            var newMat = mat * rotMat;

            /*
            Debug.Log("NewNormal:" +leftX+":"+upDirY);
            Debug.Log(mat);
            Debug.Log(rot * Vector3.forward);
            Debug.Log(newNormal);

            break;
            */
            var vec4 = new Vector4() {
                x = p.x,
                y = p.y,
                z = p.z,
                w = 0,
            };
            var lb = vec4 +  (newMat * new Vector3(-pointSize, -pointSize, 0));
            var lt = vec4 + newMat * new Vector3(-pointSize, pointSize, 0);
            var rb = vec4 + newMat * new Vector3(pointSize, -pointSize, 0);
            var rt = vec4 + newMat * new Vector3(pointSize, pointSize, 0);

            triangles[4 * i + 0] = lb;
            triangles[4 * i + 1] = rb;
            triangles[4 * i + 2] = rt;
            triangles[4 * i + 3] = lt;


            colors[4 * i + 0] = point.color;
            colors[4 * i + 1] = point.color;
            colors[4 * i + 2] = point.color;
            colors[4 * i + 3] = point.color;
            var rd = Random.Range(0, 4);
            var row = rd / 2;
            var col = rd % 2;

            uvs[4 * i + 0] = new Vector2(0+col*0.5f, 0+row*0.5f);
            uvs[4 * i + 1] = new Vector2(0.5f+col*0.5f, 0+row*0.5f);
            uvs[4 * i + 2] = new Vector2(0.5f+col*0.5f, 0.5f+row*0.5f);
            uvs[4 * i + 3] = new Vector2(0+col*0.5f, 0.5f+row*0.5f);

            normals[4 * i + 0] = new Vector3(0, 0, -1);
            normals[4 * i + 1] = new Vector3(0, 0, -1);
            normals[4 * i + 2] = new Vector3(0, 0, -1);
            normals[4 * i + 3] = new Vector3(0, 0, -1);

            indecies[6 * i + 0] = 4 * i + 0;
            indecies[6 * i + 1] = 4 * i + 1;
            indecies[6 * i + 2] = 4 * i + 2;

            indecies[6 * i + 3] = 4 * i + 0;
            indecies[6 * i + 4] = 4 * i + 2;
            indecies[6 * i + 5] = 4 * i + 3;
        }

        mesh.vertices = triangles;
        mesh.colors = colors;
        mesh.uv = uvs;
        mesh.normals = normals;
        mesh.SetIndices(indecies, MeshTopology.Triangles, 0);

    }
	
	
}
